1 <?php
2     ########################################################################
3     
/*
4     ~~~~~~ LIST OF FUNCTIONS ~~~~~~
5         getTableList() -- returns an associative array of all tables
in this application in the format tableName=>tableCaption
6         getThumbnailSpecs($tableName, $fieldName, $view) -- returns an associative array specifying the width, height and identifier of the thumbnail file.
7         createThumbnail($img, $specs) -- $specs
is an array as returned by getThumbnailSpecs(). Returns true on success, false on failure.
8         makeSafe($
string)
9         checkPermissionVal($pvn)
10         sql($statment, $o)
11         sqlValue($statment)
12         getLoggedAdmin()
13         checkUser($username, $password)
14         logOutUser()
15         getPKFieldName($tn)
16         getCSVData($tn, $pkValue, $stripTag=
true)
17         errorMsg($msg)
18         redirect($URL, $absolute=FALSE)
19         htmlRadioGroup($name, $arrValue, $arrCaption, $selectedValue, $selClass=
"", $class="", $separator="<br>")
20         htmlSelect($name, $arrValue, $arrCaption, $selectedValue, $
class="", $selectedClass="")
21         htmlSQLSelect($name, $sql, $selectedValue, $
class="", $selectedClass="")
22         isEmail($email) -- returns $email
if valid or false otherwise.
23         notifyMemberApproval($memberID) -- send an email to member acknowledging his approval
by admin, returns false if no mail is sent
24         setupMembership() -- check
if membership tables exist or not. If not, create them.
25         thisOr($this_val, $or) --
return $this_val if it has a value, or $or if not.
26         getUploadedFile($FieldName, $MaxSize=
0, $FileTypes='csv|txt', $NoRename=false, $dir='')
27         toBytes($val)
28         convertLegacyOptions($CSVList)
29         getValueGivenCaption($query, $caption)
30         undo_magic_quotes($str)
31         time24($t) --
return time in 24h format
32         time12($t) --
return time in 12h format
33         application_url($page) --
return absolute URL of provided page
34         is_ajax() --
return true if this is an ajax request, false otherwise
35         array_trim($arr) -- recursively trim provided
value/array
36         is_allowed_username($username, $exception =
false) -- returns username if valid and unique, or false otherwise (if exception is provided and same as username, no uniqueness check is performed)
37         csrf_token($validate) -- csrf-proof a form
38         get_plugins() -- scans
for installed plugins and returns them in an array ('name', 'title', 'icon' or 'glyphicon', 'admin_path')
39         maintenance_mode($new_status =
'') -- retrieves (and optionally sets) maintenance mode status
40         html_attr($str) -- prepare $str to be placed inside an HTML attribute
41         html_attr_tags_ok($str) -- same
as html_attr, but allowing HTML tags
42         Request($
var) -- class for providing sanitized values of given request variable (->sql, ->attr, ->html, ->url, and ->raw)
43         Notification() --
class for providing a standardized html notifications functionality
44         sendmail($mail) -- sends an email
using PHPMailer as specified in the assoc array $mail( ['to', 'name', 'subject', 'message', 'debug'] ) and returns true on success or an error message on failure
45         safe_html($str) -- sanitize HTML strings, and apply nl2br() to non-HTML ones
46         get_tables_info($skip_authentication =
false) -- retrieves table properties as a 2D assoc array ['table_name' => ['prop1' => 'val', ..], ..]
47         getLoggedMemberID() -- returns memberID of logged member. If no login, returns anonymous memberID
48         getLoggedGroupID() -- returns groupID of logged member, or anonymous groupID
49         getMemberInfo() -- returns an array containing the currently signed-
in member's info
50         get_group_id($user =
'') -- returns groupID of given user, or current one if empty
51         prepare_sql_set($set_array, $glue =
', ') -- Prepares data for a SET or WHERE clause, to be used in an INSERT/UPDATE query
52         insert($tn, $set_array) -- Inserts a record specified
by $set_array to the given table $tn
53         update($tn, $set_array, $where_array) -- Updates a record identified
by $where_array to date specified by $set_array in the given table $tn
54         set_record_owner($tn, $pk, $user) -- Set/update the owner of given record
55         app_datetime_format($destination =
'php', $datetime = 'd') -- get date/time format string for use with one of these: 'php' (see date function), 'mysql', 'moment'. $datetime: 'd' = date, 't' = time, 'dt' = both
56         mysql_datetime($app_datetime) -- converts $app_datetime to mysql-formatted datetime,
'yyyy-mm-dd H:i:s', or empty string on error
57         app_datetime($mysql_datetime, $datetime =
'd') -- converts $mysql_datetime to app-formatted datetime (if 2nd param is 'dt'), or empty string on error
58         to_utf8($str) -- converts
string from app-configured encoding to utf8
59         from_utf8($str) -- converts
string from utf8 to app-configured encoding
60     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61     */

62     ########################################################################
63     function get_tables_info($skip_authentication =
false){
64         
static $all_tables = array(), $accessible_tables = array();
65
66         
/* return cached results, if found */
67         
if(($skip_authentication || getLoggedAdmin()) && count($all_tables)) return $all_tables;
68         
if(!$skip_authentication && count($accessible_tables)) return $accessible_tables;
69
70         
/* table groups */
71         $tg = array(
72             
'None'
73         );
74
75         $all_tables = array(
76             
/* ['table_name' => [table props assoc array] */
77                 
'schools' => array(
78                     
'Caption' => 'Schools',
79                     
'Description' => '',
80                     
'tableIcon' => 'resources/table_icons/building.png',
81                     
'group' => $tg[0],
82                     
'homepageShowCount' => 0
83                 ),
84                 
'departments' => array(
85                     
'Caption' => 'Departments',
86                     
'Description' => '',
87                     
'tableIcon' => 'resources/table_icons/chart_organisation.png',
88                     
'group' => $tg[0],
89                     
'homepageShowCount' => 0
90                 ),
91                 
'class_time_table' => array(
92                     
'Caption' => 'Class time table',
93                     
'Description' => '',
94                     
'tableIcon' => 'resources/table_icons/blackboard_drawing.png',
95                     
'group' => $tg[0],
96                     
'homepageShowCount' => 0
97                 ),
98                 
'exam_time_table' => array(
99                     
'Caption' => 'Exam time table',
100                     
'Description' => '',
101                     
'tableIcon' => 'resources/table_icons/books.png',
102                     
'group' => $tg[0],
103                     
'homepageShowCount' => 0
104                 ),
105                 
'personal_time_table' => array(
106                     
'Caption' => 'Personal time table',
107                     
'Description' => '',
108                     
'tableIcon' => 'resources/table_icons/clock_.png',
109                     
'group' => $tg[0],
110                     
'homepageShowCount' => 0
111                 ),
112                 
'student_details' => array(
113                     
'Caption' => 'Student details',
114                     
'Description' => '',
115                     
'tableIcon' => 'resources/table_icons/administrator.png',
116                     
'group' => $tg[0],
117                     
'homepageShowCount' => 0
118                 ),
119                 
'notices' => array(
120                     
'Caption' => 'Notices',
121                     
'Description' => '',
122                     
'tableIcon' => 'resources/table_icons/clipboard_empty.png',
123                     
'group' => $tg[0],
124                     
'homepageShowCount' => 0
125                 )
126         );
127
128         
if($skip_authentication || getLoggedAdmin()) return $all_tables;
129
130         
foreach($all_tables as $tn => $ti){
131             $arrPerm = getTablePermissions($tn);
132             
if($arrPerm[0]) $accessible_tables[$tn] = $ti;
133         }
134
135         
return $accessible_tables;
136     }
137     #########################################################
138     
if(!function_exists('getTableList')){
139         function getTableList($skip_authentication =
false){
140             $arrTables = array(
141                 
'schools' => 'Schools',
142                 
'departments' => 'Departments',
143                 
'class_time_table' => 'Class time table',
144                 
'exam_time_table' => 'Exam time table',
145                 
'personal_time_table' => 'Personal time table',
146                 
'student_details' => 'Student details',
147                 
'notices' => 'Notices'
148             );
149
150             
return $arrTables;
151         }
152     }
153     ########################################################################
154     function getThumbnailSpecs($tableName, $fieldName, $view){
155         
return FALSE;
156     }
157     ########################################################################
158     function createThumbnail($img, $specs){
159         $w=$specs[
'width'];
160         $h=$specs[
'height'];
161         $id=$specs[
'identifier'];
162         $path=dirname($img);
163
164         
// image doesn't exist or inaccessible?
165         
if(!$size=@getimagesize($img)) return FALSE;
166
167         
// calculate thumbnail size to maintain aspect ratio
168         $ow=$size[
0]; // original image width
169         $oh=$size[
1]; // original image height
170         $twbh=$h/$oh*$ow;
// calculated thumbnail width based on given height
171         $thbw=$w/$ow*$oh;
// calculated thumbnail height based on given width
172         
if($w && $h){
173             
if($twbh>$w) $h=$thbw;
174             
if($thbw>$h) $w=$twbh;
175         }elseif($w){
176             $h=$thbw;
177         }elseif($h){
178             $w=$twbh;
179         }
else{
180             
return FALSE;
181         }
182
183         
// dir not writeable?
184         
if(!is_writable($path)) return FALSE;
185
186         
// GD lib not loaded?
187         
if(!function_exists('gd_info')) return FALSE;
188         $gd=gd_info();
189
190         
// GD lib older than 2.0?
191         preg_match(
'/\d/', $gd['GD Version'], $gdm);
192         
if($gdm[0]<2) return FALSE;
193
194         
// get file extension
195         preg_match(
'/\.[a-zA-Z]{3,4}$/U', $img, $matches);
196         $ext=strtolower($matches[
0]);
197
198         
// check if supplied image is supported and specify actions based on file type
199         
if($ext=='.gif'){
200             
if(!$gd['GIF Create Support']) return FALSE;
201             $thumbFunc=
'imagegif';
202         }elseif($ext==
'.png'){
203             
if(!$gd['PNG Support']) return FALSE;
204             $thumbFunc=
'imagepng';
205         }elseif($ext==
'.jpg' || $ext=='.jpe' || $ext=='.jpeg'){
206             
if(!$gd['JPG Support'] && !$gd['JPEG Support']) return FALSE;
207             $thumbFunc=
'imagejpeg';
208         }
else{
209             
return FALSE;
210         }
211
212         
// determine thumbnail file name
213         $ext=$matches[
0];
214         $thumb=substr($img,
0, -5).str_replace($ext, $id.$ext, substr($img, -5));
215
216         
// if the original image smaller than thumb, then just copy it to thumb
217         
if($h>$oh && $w>$ow){
218             
return (@copy($img, $thumb) ? TRUE : FALSE);
219         }
220
221         
// get image data
222         
if(!$imgData=imagecreatefromstring(implode('', file($img)))) return FALSE;
223
224         
// finally, create thumbnail
225         $thumbData=imagecreatetruecolor($w, $h);
226
227         
//preserve transparency of png and gif images
228         
if($thumbFunc=='imagepng'){
229             
if(($clr=@imagecolorallocate($thumbData, 0, 0, 0))!=-1){
230                 @imagecolortransparent($thumbData, $clr);
231                 @imagealphablending($thumbData,
false);
232                 @imagesavealpha($thumbData,
true);
233             }
234         }elseif($thumbFunc==
'imagegif'){
235             @imagealphablending($thumbData,
false);
236             $transIndex=imagecolortransparent($imgData);
237             
if($transIndex>=0){
238                 $transClr=imagecolorsforindex($imgData, $transIndex);
239                 $transIndex=imagecolorallocatealpha($thumbData, $transClr[
'red'], $transClr['green'], $transClr['blue'], 127);
240                 imagefill($thumbData,
0, 0, $transIndex);
241             }
242         }
243
244         
// resize original image into thumbnail
245         
if(!imagecopyresampled($thumbData, $imgData, 0, 0 , 0, 0, $w, $h, $ow, $oh)) return FALSE;
246         unset($imgData);
247
248         
// gif transparency
249         
if($thumbFunc=='imagegif' && $transIndex>=0){
250             imagecolortransparent($thumbData, $transIndex);
251             
for($y=0; $y<$h; ++$y)
252                 
for($x=0; $x<$w; ++$x)
253                     
if(((imagecolorat($thumbData, $x, $y)>>24) & 0x7F) >= 100) imagesetpixel($thumbData, $x, $y, $transIndex);
254             imagetruecolortopalette($thumbData,
true, 255);
255             imagesavealpha($thumbData,
false);
256         }
257
258         
if(!$thumbFunc($thumbData, $thumb)) return FALSE;
259         unset($thumbData);
260
261         
return TRUE;
262     }
263     ########################################################################
264     function makeSafe($
string, $is_gpc = true){
265         
if($is_gpc) $string = (get_magic_quotes_gpc() ? stripslashes($string) : $string);
266         
if(!db_link()){ sql("select 1+1", $eo); }
267
268         
// prevent double escaping
269         $na = explode(
',', "\x00,\n,\r,',\",\x1a");
270         $escaped =
true;
271         $nosc =
true; // no special chars exist
272         
foreach($na as $ns){
273             $dan = substr_count($
string, $ns);
274             $esdan = substr_count($
string, "\\{$ns}");
275             
if($dan != $esdan) $escaped = false;
276             
if($dan) $nosc = false;
277         }
278         
if($nosc){
279             
// find unescaped \
280             $dan = substr_count($
string, '\\');
281             $esdan = substr_count($
string, '\\\\');
282             
if($dan != $esdan * 2) $escaped = false;
283         }
284
285         
return ($escaped ? $string : db_escape($string));
286     }
287     ########################################################################
288     function checkPermissionVal($pvn){
289         
// fn to make sure the value in the given POST variable is 0, 1, 2 or 3
290         
// if the value is invalid, it default to 0
291         $pvn=intval($_POST[$pvn]);
292         
if($pvn!=1 && $pvn!=2 && $pvn!=3){
293             
return 0;
294         }
else{
295             
return $pvn;
296         }
297     }
298     ########################################################################
299     
if(!function_exists('sql')){
300         function sql($statment, &$o){
301
302             
/*
303                 Supported options that can be passed
in $o options array (as array keys):
304                 
'silentErrors': If true, errors will be returned in $o['error'] rather than displaying them on screen and exiting.
305             */

306
307             
global $Translation;
308             
static $connected = false, $db_link;
309
310             $dbServer = config(
'dbServer');
311             $dbUsername = config(
'dbUsername');
312             $dbPassword = config(
'dbPassword');
313             $dbDatabase = config(
'dbDatabase');
314
315             ob_start();
316
317             
if(!$connected){
318                 
/****** Connect to MySQL ******/
319                 
if(!extension_loaded('mysql') && !extension_loaded('mysqli')){
320                     $o[
'error'] = 'PHP is not configured to connect to MySQL on this machine. Please see <a href="http://www.php.net/manual/en/ref.mysql.php">this page</a> for help on how to configure MySQL.';
321                     
if($o['silentErrors']) return false;
322
323                     echo Notification::placeholder();
324                     echo Notification::show(array(
325                         
'message' => $o['error'],
326                         
'class' => 'danger',
327                         
'dismiss_seconds' => 7200
328                     ));
329                     echo ob_get_clean();
330                     exit;
331                 }
332
333                 
if(!($db_link = @db_connect($dbServer, $dbUsername, $dbPassword))){
334                     $o[
'error'] = db_error($db_link, true);
335                     
if($o['silentErrors']) return false;
336
337                     echo Notification::placeholder();
338                     echo Notification::show(array(
339                         
'message' => $o['error'],
340                         
'class' => 'danger',
341                         
'dismiss_seconds' => 7200
342                     ));
343                     echo ob_get_clean();
344                     exit;
345                 }
346
347                 
/****** Select DB ********/
348                 
if(!db_select_db($dbDatabase, $db_link)){
349                     $o[
'error'] = db_error($db_link);
350                     
if($o['silentErrors']) return false;
351
352                     echo Notification::placeholder();
353                     echo Notification::show(array(
354                         
'message' => $o['error'],
355                         
'class' => 'danger',
356                         
'dismiss_seconds' => 7200
357                     ));
358                     echo ob_get_clean();
359                     exit;
360                 }
361
362                 $connected =
true;
363             }
364
365             
if(!$result = @db_query($statment, $db_link)){
366                 
if(!stristr($statment, "show columns")){
367                     
// retrieve error codes
368                     $errorNum = db_errno($db_link);
369                     $errorMsg = htmlspecialchars(db_error($db_link));
370
371                     
if(getLoggedAdmin()) $errorMsg .= "<pre class=\"ltr\">{$Translation['query:']}\n" . htmlspecialchars($statment) . "</pre><i class=\"text-right\">{$Translation['admin-only info']}</i>";
372
373                     
if($o['silentErrors']){ $o['error'] = $errorMsg; return false; }
374
375                     echo Notification::placeholder();
376                     echo Notification::show(array(
377                         
'message' => $errorMsg,
378                         
'class' => 'danger',
379                         
'dismiss_seconds' => 7200
380                     ));
381                     echo ob_get_clean();
382                     exit;
383                 }
384             }
385
386             ob_end_clean();
387             
return $result;
388         }
389     }
390
391     ########################################################################
392     function sqlValue($statment){
393         
// executes a statment that retreives a single data value and returns the value retrieved
394         
if(!$res=sql($statment, $eo)){
395             
return FALSE;
396         }
397         
if(!$row=db_fetch_row($res)){
398             
return FALSE;
399         }
400         
return $row[0];
401     }
402     ########################################################################
403     function getLoggedAdmin(){
404         
// checks session variables to see whether the admin is logged or not
405         
// if not, it returns FALSE
406         
// if logged, it returns the user id
407
408         $adminConfig = config(
'adminConfig');
409
410         
if($_SESSION['adminUsername']!=''){
411             
return $_SESSION['adminUsername'];
412         }elseif($_SESSION[
'memberID']==$adminConfig['adminUsername']){
413             $_SESSION[
'adminUsername']=$_SESSION['memberID'];
414             
return $_SESSION['adminUsername'];
415         }
else{
416             
return FALSE;
417         }
418     }
419     ########################################################################
420     function checkUser($username, $password){
421         
// checks given username and password for validity
422         
// if valid, registers the username in a session and returns true
423         
// else, return FALSE and destroys session
424
425         $adminConfig = config(
'adminConfig');
426         
if($username != $adminConfig['adminUsername'] || md5($password) != $adminConfig['adminPassword']){
427             
return FALSE;
428         }
429
430         $_SESSION[
'adminUsername'] = $username;
431         $_SESSION[
'memberGroupID'] = sqlValue("select groupID from membership_users where memberID='" . makeSafe($username) ."'");
432         $_SESSION[
'memberID'] = $username;
433         
return TRUE;
434     }
435     ########################################################################
436     function logOutUser(){
437         
// destroys current session
438         
if(isset($_COOKIE[session_name()])){
439             setcookie(session_name(),
'', time() - 42000, '/');
440         }
441         
if(isset($_COOKIE[session_name() . '_rememberMe'])){
442             setcookie(session_name() .
'_rememberMe', '', time() - 42000);
443         }
444         session_destroy();
445         $_SESSION = array();
446     }
447     ########################################################################
448     function getPKFieldName($tn){
449         
// get pk field name of given table
450
451         $stn = makeSafe($tn,
false);
452         
if(!$res = sql("show fields from `$stn`", $eo)){
453             
return false;
454         }
455
456         
while($row = db_fetch_assoc($res)){
457             
if($row['Key'] == 'PRI'){
458                 
return $row['Field'];
459             }
460         }
461
462         
return false;
463     }
464     ########################################################################
465     function getCSVData($tn, $pkValue, $stripTags=
true){
466         
// get pk field name for given table
467         
if(!$pkField=getPKFieldName($tn)){
468             
return "";
469         }
470
471         
// get a concat string to produce a csv list of field values for given table record
472         
if(!$res=sql("show fields from `$tn`", $eo)){
473             
return "";
474         }
475         
while($row=db_fetch_assoc($res)){
476             $csvFieldList.=
"`{$row['Field']}`,";
477         }
478         $csvFieldList=substr($csvFieldList,
0, -1);
479
480         $csvData=sqlValue(
"select CONCAT_WS(', ', $csvFieldList) from `$tn` where `$pkField`='" . makeSafe($pkValue, false) . "'");
481
482         
return ($stripTags ? strip_tags($csvData) : $csvData);
483     }
484     ########################################################################
485     function errorMsg($msg){
486         echo
"<div class=\"alert alert-danger\">{$msg}</div>";
487     }
488     ########################################################################
489     function redirect($url, $absolute =
false){
490         $fullURL = ($absolute ? $url : application_url($url));
491         
if(!headers_sent()) header("Location: {$fullURL}");
492
493         echo
"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;url={$fullURL}\">";
494         echo
"<br><br><a href=\"{$fullURL}\">Click here</a> if you aren't automatically redirected.";
495         exit;
496     }
497     ########################################################################
498     function htmlRadioGroup($name, $arrValue, $arrCaption, $selectedValue, $selClass =
"text-primary", $class = "", $separator = "<br>"){
499         
if(!is_array($arrValue)) return '';
500
501         ob_start();
502         ?>
503         <div
class="radio %%CLASS%%"><label>
504             <input type=
"radio" name="%%NAME%%" id="%%ID%%" value="%%VALUE%%" %%CHECKED%%> %%LABEL%%
505         </label></div>
506         <?php
507         $template = ob_get_contents();
508         ob_end_clean();
509
510         $
out = '';
511         
for($i = 0; $i < count($arrValue); $i++){
512             $replacements = array(
513                 
'%%CLASS%%' => html_attr($arrValue[$i] == $selectedValue ? $selClass :$class),
514                 
'%%NAME%%' => html_attr($name),
515                 
'%%ID%%' => html_attr($name . $i),
516                 
'%%VALUE%%' => html_attr($arrValue[$i]),
517                 
'%%LABEL%%' => $arrCaption[$i],
518                 
'%%CHECKED%%' => ($arrValue[$i]==$selectedValue ? " checked" : "")
519             );
520             $
out .= str_replace(array_keys($replacements), array_values($replacements), $template);
521         }
522
523         
return $out;
524     }
525     ########################################################################
526     function htmlSelect($name, $arrValue, $arrCaption, $selectedValue, $
class="", $selectedClass=""){
527         
if($selectedClass==""){
528             $selectedClass=$
class;
529         }
530         
if(is_array($arrValue)){
531             $
out="<select name=\"$name\" id=\"$name\">";
532             
for($i=0; $i<count($arrValue); $i++){
533                 $
out.="<option value=\"".$arrValue[$i]."\"".($arrValue[$i]==$selectedValue ? " selected class=\"$class\"" : " class=\"$selectedClass\"").">".$arrCaption[$i]."</option>";
534             }
535             $
out.="</select>";
536         }
537         
return $out;
538     }
539     ########################################################################
540     function htmlSQLSelect($name, $sql, $selectedValue, $
class="", $selectedClass=""){
541         $arrVal[]=
'';
542         $arrCap[]=
'';
543         
if($res=sql($sql, $eo)){
544             
while($row=db_fetch_row($res)){
545                 $arrVal[]=$row[
0];
546                 $arrCap[]=$row[
1];
547             }
548             
return htmlSelect($name, $arrVal, $arrCap, $selectedValue, $class, $selectedClass);
549         }
else{
550             
return "";
551         }
552     }
553     ########################################################################
554     function bootstrapSelect($name, $arrValue, $arrCaption, $selectedValue, $
class = '', $selectedClass = ''){
555         
if($selectedClass == '') $selectedClass = $class;
556
557         $
out = "<select class=\"form-control\" name=\"{$name}\" id=\"{$name}\">";
558         
if(is_array($arrValue)){
559             
for($i = 0; $i < count($arrValue); $i++){
560                 $selected =
"class=\"{$class}\"";
561                 
if($arrValue[$i] == $selectedValue) $selected = "selected class=\"{$selectedClass}\"";
562                 $
out .= "<option value=\"{$arrValue[$i]}\" {$selected}>{$arrCaption[$i]}</option>";
563             }
564         }
565         $
out .= '</select>';
566
567         
return $out;
568     }
569     ########################################################################
570     function bootstrapSQLSelect($name, $sql, $selectedValue, $
class = '', $selectedClass = ''){
571         $arrVal[] =
'';
572         $arrCap[] =
'';
573         
if($res = sql($sql, $eo)){
574             
while($row = db_fetch_row($res)){
575                 $arrVal[] = $row[
0];
576                 $arrCap[] = $row[
1];
577             }
578             
return bootstrapSelect($name, $arrVal, $arrCap, $selectedValue, $class, $selectedClass);
579         }
580
581         
return '';
582     }
583     ########################################################################
584     function isEmail($email){
585         
if(preg_match('/^([*+!.&#$¦\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,45})$/i', $email)){
586             
return $email;
587         }
else{
588             
return FALSE;
589         }
590     }
591     ########################################################################
592     function notifyMemberApproval($memberID){
593         $adminConfig = config(
'adminConfig');
594         $memberID = strtolower($memberID);
595
596         $email = sqlValue(
"select email from membership_users where lcase(memberID)='{$memberID}'");
597
598         
return sendmail(array(
599             
'to' => $email,
600             
'name' => $memberID,
601             
'subject' => $adminConfig['approvalSubject'],
602             
'message' => nl2br($adminConfig['approvalMessage'])
603         ));
604     }
605     ########################################################################
606     function setupMembership(){
607         
// run once per request
608         
static $executed = false;
609         
if($executed) return;
610         $executed =
true;
611
612         
/* abort if current page is one of the following exceptions */
613         $exceptions = array(
'pageEditMember.php', 'membership_passwordReset.php', 'membership_profile.php', 'membership_signup.php', 'pageChangeMemberStatus.php', 'pageDeleteGroup.php', 'pageDeleteMember.php', 'pageEditGroup.php', 'pageEditMemberPermissions.php', 'pageRebuildFields.php', 'pageSettings.php');
614         
if(in_array(basename($_SERVER['PHP_SELF']), $exceptions)) return;
615
616         $eo = array(
'silentErrors' => true);
617
618         $adminConfig = config(
'adminConfig');
619         $today = @date(
'Y-m-d');
620
621         $membership_tables = array(
622             
'membership_groups' => "CREATE TABLE IF NOT EXISTS membership_groups (groupID int unsigned NOT NULL auto_increment, name varchar(20), description text, allowSignup tinyint, needsApproval tinyint, PRIMARY KEY (groupID)) CHARSET " . mysql_charset,
623             
'membership_users' => "CREATE TABLE IF NOT EXISTS membership_users (memberID varchar(20) NOT NULL, passMD5 varchar(40), email varchar(100), signupDate date, groupID int unsigned, isBanned tinyint, isApproved tinyint, custom1 text, custom2 text, custom3 text, custom4 text, comments text, PRIMARY KEY (memberID)) CHARSET " . mysql_charset,
624             
'membership_grouppermissions' => "CREATE TABLE IF NOT EXISTS membership_grouppermissions (permissionID int unsigned NOT NULL auto_increment, groupID int, tableName varchar(100), allowInsert tinyint, allowView tinyint NOT NULL DEFAULT '0', allowEdit tinyint NOT NULL DEFAULT '0', allowDelete tinyint NOT NULL DEFAULT '0', PRIMARY KEY (permissionID)) CHARSET " . mysql_charset,
625             
'membership_userrecords' => "CREATE TABLE IF NOT EXISTS membership_userrecords (recID bigint unsigned NOT NULL auto_increment, tableName varchar(100), pkValue varchar(255), memberID varchar(20), dateAdded bigint unsigned, dateUpdated bigint unsigned, groupID int, PRIMARY KEY (recID)) CHARSET " . mysql_charset,
626             
'membership_userpermissions' => "CREATE TABLE IF NOT EXISTS membership_userpermissions (permissionID int unsigned NOT NULL auto_increment, memberID varchar(20) NOT NULL, tableName varchar(100), allowInsert tinyint, allowView tinyint NOT NULL DEFAULT '0', allowEdit tinyint NOT NULL DEFAULT '0', allowDelete tinyint NOT NULL DEFAULT '0', PRIMARY KEY (permissionID)) CHARSET " . mysql_charset
627         );
628
629         //
get db tables
630         $tables = array();
631         $res = sql(
"show tables", $eo);
632
633         
if(!$res){
634             include_once(dirname(__FILE__) .
'/../header.php');
635             echo $eo[
'error'];
636             include_once(dirname(__FILE__) .
'/../footer.php');
637             exit;
638         }
639
640         
while($row = db_fetch_array($res)) $tables[] = $row[0];
641
642         // check
if membership tables exist or not
643         
foreach($membership_tables as $tn => $tdef){
644             
if(!in_array($tn, $tables)){
645                 sql($tdef, $eo);
646             }
647         }
648
649         // check membership_users definition
650         $membership_users = array();
651         $res = sql(
"show columns from membership_users", $eo);
652         
while($row = db_fetch_assoc($res)) $membership_users[$row['Field']] = $row;
653
654         
if(!in_array('pass_reset_key', array_keys($membership_users))) @db_query("ALTER TABLE membership_users ADD COLUMN pass_reset_key VARCHAR(100)");
655         
if(!in_array('pass_reset_expiry', array_keys($membership_users))) @db_query("ALTER TABLE membership_users ADD COLUMN pass_reset_expiry INT UNSIGNED");
656         
if(!$membership_users['groupID']['Key']) @db_query("ALTER TABLE membership_users ADD INDEX groupID (groupID)");
657
658         // create membership indices
if not existing
659         $membership_userrecords = array();
660         $res = sql(
"show keys from membership_userrecords", $eo);
661         
while($row = db_fetch_assoc($res)) $membership_userrecords[$row['Key_name']][$row['Seq_in_index']] = $row;
662
663         
if(!$membership_userrecords['pkValue'][1]) @db_query("ALTER TABLE membership_userrecords ADD INDEX pkValue (pkValue)");
664         
if(!$membership_userrecords['tableName'][1]) @db_query("ALTER TABLE membership_userrecords ADD INDEX tableName (tableName)");
665         
if(!$membership_userrecords['memberID'][1]) @db_query("ALTER TABLE membership_userrecords ADD INDEX memberID (memberID)");
666         
if(!$membership_userrecords['groupID'][1]) @db_query("ALTER TABLE membership_userrecords ADD INDEX groupID (groupID)");
667         
if(!$membership_userrecords['tableName_pkValue'][1] || !$membership_userrecords['tableName_pkValue'][2]) @db_query("ALTER IGNORE TABLE membership_userrecords ADD UNIQUE INDEX tableName_pkValue (tableName, pkValue)");
668
669         // retreive anonymous and admin groups and their permissions
670         $anon_group = $adminConfig[
'anonymousGroup'];
671         $anon_user = strtolower($adminConfig[
'anonymousMember']);
672         $admin_group =
'Admins';
673         $admin_user = strtolower($adminConfig[
'adminUsername']);
674         $groups_permissions = array();
675         $res = sql(
676             
"select g.groupID, g.name, gp.tableName, gp.allowInsert, gp.allowView, gp.allowEdit, gp.allowDelete " .
677             
"from membership_groups g left join membership_grouppermissions gp on g.groupID=gp.groupID " .
678             
"where g.name='" . makeSafe($admin_group) . "' or g.name='" . makeSafe($anon_group) . "' " .
679             
"order by g.groupID, gp.tableName", $eo
680         );
681         
while($row = db_fetch_assoc($res)) $groups_permissions[] = $row;
682
683         // check anonymous
group and user and create if necessary
684         $anon_group_id =
false;
685         
foreach($groups_permissions as $group){
686             
if($group['name'] == $anon_group){
687                 $anon_group_id = $
group['groupID'];
688                 
break;
689             }
690         }
691
692         
if(!$anon_group_id){
693             sql(
"insert into membership_groups set name='" . makeSafe($anon_group) . "', allowSignup=0, needsApproval=0, description='Anonymous group created automatically on " . @date("Y-m-d") . "'", $eo);
694             $anon_group_id = db_insert_id();
695         }
696
697         
if($anon_group_id){
698             $anon_user_db = sqlValue(
"select lcase(memberID) from membership_users where lcase(memberID)='" . makeSafe($anon_user) . "' and groupID='{$anon_group_id}'");
699             
if(!$anon_user_db || $anon_user_db != $anon_user){
700                 sql(
"delete from membership_users where groupID='{$anon_group_id}'", $eo);
701                 sql(
"insert into membership_users set memberID='" . makeSafe($anon_user) . "', signUpDate='{$today}', groupID='{$anon_group_id}', isBanned=0, isApproved=1, comments='Anonymous member created automatically on {$today}'", $eo);
702             }
703         }
704
705         // check admin
group and user and create if necessary
706         $admin_group_id =
false;
707         
foreach($groups_permissions as $group){
708             
if($group['name'] == $admin_group){
709                 $admin_group_id = $
group['groupID'];
710                 
break;
711             }
712         }
713
714         
if(!$admin_group_id){
715             sql(
"insert into membership_groups set name='" . makeSafe($admin_group) . "', allowSignup=0, needsApproval=1, description='Admin group created automatically on {$today}'", $eo);
716             $admin_group_id = db_insert_id();
717         }
718
719         
if($admin_group_id){
720             // check that admins can access all tables
721             $all_tables = getTableList(
true);
722             $tables_ok = $perms_ok = array();
723             
foreach($all_tables as $tn => $tc) $tables_ok[$tn] = $perms_ok[$tn] = false;
724
725             
foreach($groups_permissions as $group){
726                 
if($group['name'] == $admin_group){
727                     
if(isset($tables_ok[$group['tableName']])){
728                         $tables_ok[$
group['tableName']] = true;
729                         
if($group['allowInsert'] == 1 && $group['allowDelete'] == 3 && $group['allowEdit'] == 3 && $group['allowView'] == 3){
730                             $perms_ok[$
group['tableName']] = true;
731                         }
732                     }
733                 }
734             }
735
736             //
if any table has no record in Admins permissions, create one for it
737             $grant_sql = array();
738             
foreach($tables_ok as $tn => $status){
739                 
if(!$status) $grant_sql[] = "({$admin_group_id}, '{$tn}')";
740             }
741
742             
if(count($grant_sql)){
743                 sql(
"insert into membership_grouppermissions (groupID, tableName) values " . implode(',', $grant_sql), $eo);
744             }
745
746             // check admin permissions and update
if necessary
747             $perms_sql = array();
748             
foreach($perms_ok as $tn => $status){
749                 
if(!$status) $perms_sql[] = "'{$tn}'";
750             }
751
752             
if(count($perms_sql)){
753                 sql(
"update membership_grouppermissions set allowInsert=1, allowView=3, allowEdit=3, allowDelete=3 where groupID={$admin_group_id} and tableName in (" . implode(',', $perms_sql) . ")", $eo);
754             }
755
756             // check
if super admin is stored in the users table and add him if not
757             $admin_user_exists = sqlValue(
"select count(1) from membership_users where lcase(memberID)='" . makeSafe($admin_user)."' and groupID='{$admin_group_id}'");
758             
if(!$admin_user_exists){
759                 sql(
"insert into membership_users set memberID='" . makeSafe($admin_user) . "', passMD5='{$adminConfig['adminPassword']}', email='{$adminConfig['senderEmail']}', signUpDate='{$today}', groupID='{$admin_group_id}', isBanned=0, isApproved=1, comments='Admin member created automatically on {$today}'", $eo);
760             }
761         }
762     }
763
764     ########################################################################
765     function thisOr($this_val, $or =
'&nbsp;'){
766         
return ($this_val != '' ? $this_val : $or);
767     }
768     ########################################################################
769     function getUploadedFile($FieldName, $MaxSize=
0, $FileTypes='csv|txt', $NoRename=false, $dir=''){
770         $currDir=dirname(__FILE__);
771         
if(is_array($_FILES)){
772             $f = $_FILES[$FieldName];
773         }
else{
774             
return 'Your php settings don\'t allow file uploads.';
775         }
776
777         
if(!$MaxSize){
778             $MaxSize=toBytes(ini_get(
'upload_max_filesize'));
779         }
780
781         
if(!is_dir("$currDir/csv")){
782             @mkdir(
"$currDir/csv");
783         }
784
785         $dir=(is_dir($dir) && is_writable($dir) ? $dir :
"$currDir/csv/");
786
787         
if($f['error']!=4 && $f['name']!=''){
788             
if($f['size']>$MaxSize || $f['error']){
789                 
return 'File size exceeds maximum allowed of '.intval($MaxSize / 1024).'KB';
790             }
791             
if(!preg_match('/\.('.$FileTypes.')$/i', $f['name'], $ft)){
792                 
return 'File type not allowed. Only these file types are allowed: '.str_replace('|', ', ', $FileTypes);
793             }
794
795             
if($NoRename){
796                 $n = str_replace(
' ', '_', $f['name']);
797             }
else{
798                 $n = microtime();
799                 $n = str_replace(
' ', '_', $n);
800                 $n = str_replace(
'0.', '', $n);
801                 $n .= $ft[
0];
802             }
803
804             
if(!@move_uploaded_file($f['tmp_name'], $dir . $n)){
805                 
return 'Couldn\'t save the uploaded file. Try chmoding the upload folder "'.$dir.'" to 777.';
806             }
else{
807                 @chmod($dir.$n,
0666);
808                 
return $dir.$n;
809             }
810         }
811         
return 'An error occured while uploading the file. Please try again.';
812     }
813     ########################################################################
814     function toBytes($val){
815         $val = trim($val);
816         $last = strtolower($val{strlen($val)-
1});
817         
switch($last){
818              // The
'G' modifier is available since PHP 5.1.0
819              
case 'g':
820                     $val *=
1024;
821              
case 'm':
822                     $val *=
1024;
823              
case 'k':
824                     $val *=
1024;
825         }
826
827         
return $val;
828     }
829     ########################################################################
830     function convertLegacyOptions($CSVList){
831         $CSVList=str_replace(
';;;', ';||', $CSVList);
832         $CSVList=str_replace(
';;', '||', $CSVList);
833         
return $CSVList;
834     }
835     ########################################################################
836     function getValueGivenCaption($query, $caption){
837         
if(!preg_match('/select\s+(.*?)\s*,\s*(.*?)\s+from\s+(.*?)\s+order by.*/i', $query, $m)){
838             
if(!preg_match('/select\s+(.*?)\s*,\s*(.*?)\s+from\s+(.*)/i', $query, $m)){
839                 
return '';
840             }
841         }
842
843         //
get where clause if present
844         
if(preg_match('/\s+from\s+(.*?)\s+where\s+(.*?)\s+order by.*/i', $query, $mw)){
845             $
where="where ($mw[2]) AND";
846             $m[
3]=$mw[1];
847         }
else{
848             $
where='where';
849         }
850
851         $caption=makeSafe($caption);
852         
return sqlValue("SELECT $m[1] FROM $m[3] $where $m[2]='$caption'");
853     }
854     ########################################################################
855     function undo_magic_quotes($str){
856         
return (get_magic_quotes_gpc() ? stripslashes($str) : $str);
857     }
858     ########################################################################
859     function time24($t =
false){
860         
if($t === false) $t = date('Y-m-d H:i:s'); // time now if $t not passed
861         elseif(!$t)
return ''; // empty string if $t empty
862         
return date('H:i:s', strtotime($t));
863     }
864     ########################################################################
865     function time12($t =
false){
866         
if($t === false) $t = date('Y-m-d H:i:s'); // time now if $t not passed
867         elseif(!$t)
return ''; // empty string if $t empty
868         
return date('h:i:s A', strtotime($t));
869     }
870     ########################################################################
871     function application_url($page =
'', $s = false){
872         
if($s === false) $s = $_SERVER;
873         $ssl = (!empty($s[
'HTTPS']) && $s['HTTPS'] == 'on');
874         $http = ($ssl ?
'https:' : 'http:');
875         $port = $s[
'SERVER_PORT'];
876         $port = ((!$ssl && $port ==
'80') || ($ssl && $port == '443')) ? '' : ':' . $port;
877         $host = (isset($s[
'HTTP_HOST']) ? $s['HTTP_HOST'] : $s['SERVER_NAME'] . $port);
878         $uri = dirname($s[
'SCRIPT_NAME']);
879
880         
/* app folder name (without the ending /admin part) */
881         $app_folder_is_admin =
false;
882         $app_folder = substr(dirname(__FILE__),
0, -6);
883         
if(substr($app_folder, -6, 6) == '/admin' || substr($app_folder, -6, 6) == '\\admin')
884             $app_folder_is_admin =
true;
885
886         
if(substr($uri, -12, 12) == '/admin/admin') $uri = substr($uri, 0, -6);
887         elseif(substr($uri, -
6, 6) == '/admin' && !$app_folder_is_admin) $uri = substr($uri, 0, -6);
888         elseif($uri ==
'/' || $uri == '\\') $uri = '';
889
890         
return "{$http}//{$host}{$uri}/{$page}";
891     }
892     ########################################################################
893     function is_ajax(){
894         
return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
895     }
896     ########################################################################
897     function array_trim($arr){
898         
if(!is_array($arr)) return trim($arr);
899         
return array_map('array_trim', $arr);
900     }
901     ########################################################################
902     function is_allowed_username($username, $exception =
false){
903         $username = trim(strtolower($username));
904         
if(!preg_match('/^[a-z0-9][a-z0-9 _.@]{3,19}$/', $username) || preg_match('/(@@| |\.\.|___)/', $username)) return false;
905
906         
if($username == $exception) return $username;
907
908         
if(sqlValue("select count(1) from membership_users where lcase(memberID)='{$username}'")) return false;
909         
return $username;
910     }
911     ########################################################################
912     
/*
913         
if called without parameters, looks for a non-expired token in the user's session (or creates one if
914         none found) and returns html code to insert
into the form to be protected.
915
916         
if set to true, validates token sent in $_REQUEST against that stored in the session
917         and returns
true if valid or false if invalid, absent or expired.
918
919         usage:
920             
1. in a new form that needs csrf proofing: echo csrf_token();
921                >> 
in case of ajax requests and similar, retrieve token directly
922                   
by calling csrf_token(false, true);
923             
2. when validating a submitted form: if(!csrf_token(true)){ reject_submission_somehow(); }
924     */

925     function csrf_token($validate =
false, $token_only = false){
926         $token_age =
60 * 60;
927         
/* retrieve token from session */
928         $csrf_token = (isset($_SESSION[
'csrf_token']) ? $_SESSION['csrf_token'] : false);
929         $csrf_token_expiry = (isset($_SESSION[
'csrf_token_expiry']) ? $_SESSION['csrf_token_expiry'] : false);
930
931         
if(!$validate){
932             
/* create a new token if necessary */
933             
if($csrf_token_expiry < time() || !$csrf_token){
934                 $csrf_token = md5(uniqid(rand(),
true));
935                 $csrf_token_expiry = time() + $token_age;
936                 $_SESSION[
'csrf_token'] = $csrf_token;
937                 $_SESSION[
'csrf_token_expiry'] = $csrf_token_expiry;
938             }
939
940             
if($token_only) return $csrf_token;
941             
return '<input type="hidden" id="csrf_token" name="csrf_token" value="' . $csrf_token . '">';
942         }
943
944         
/* validate submitted token */
945         $user_token = (isset($_REQUEST[
'csrf_token']) ? $_REQUEST['csrf_token'] : false);
946         
if($csrf_token_expiry < time() || !$user_token || $user_token != $csrf_token){
947             
return false;
948         }
949
950         
return true;
951     }
952     ########################################################################
953     function get_plugins(){
954         $plugins = array();
955         $plugins_path = dirname(__FILE__) .
'/../plugins/';
956
957         
if(!is_dir($plugins_path)) return $plugins;
958
959         $pd = dir($plugins_path);
960         
while(false !== ($plugin = $pd->read())){
961             
if(!is_dir($plugins_path . $plugin) || in_array($plugin, array('projects', 'plugins-resources', '.', '..'))) continue;
962
963             $info_file =
"{$plugins_path}{$plugin}/plugin-info.json";
964             
if(!is_file($info_file)) continue;
965
966             $plugins[] = json_decode(file_get_contents($info_file),
true);
967             $plugins[count($plugins) -
1]['admin_path'] = "../plugins/{$plugin}";
968         }
969         $pd->close();
970
971         
return $plugins;
972     }
973     ########################################################################
974     function maintenance_mode($new_status =
''){
975         $maintenance_file = dirname(__FILE__) .
'/.maintenance';
976
977         
if($new_status === true){
978             
/* turn on maintenance mode */
979             @touch($maintenance_file);
980         }elseif($new_status ===
false){
981             
/* turn off maintenance mode */
982             @unlink($maintenance_file);
983         }
984
985         
/* return current maintenance mode status */
986         
return is_file($maintenance_file);
987     }
988     ########################################################################
989     function handle_maintenance($echo =
false){
990         
if(!maintenance_mode()) return;
991
992         
global $Translation;
993         $adminConfig = config(
'adminConfig');
994
995         $admin = getLoggedAdmin();
996         
if($admin){
997             
return ($echo ? '<div class="alert alert-danger" style="margin: 5em auto -5em;"><b>' . $Translation['maintenance mode admin notification'] . '</b></div>' : '');
998         }
999
1000         
if(!$echo) exit;
1001
1002         exit(
'<div class="alert alert-danger" style="margin-top: 5em; font-size: 2em;"><i class="glyphicon glyphicon-exclamation-sign"></i> ' . $adminConfig['maintenance_mode_message'] . '</div>');
1003     }
1004     #########################################################
1005     function html_attr($str){
1006         
if(version_compare(PHP_VERSION, '5.2.3') >= 0) return htmlspecialchars($str, ENT_QUOTES, datalist_db_encoding, false);
1007         
return htmlspecialchars($str, ENT_QUOTES, datalist_db_encoding);
1008     }
1009     #########################################################
1010     function html_attr_tags_ok($str){
1011         
// use this instead of html_attr() if you don't want html tags to be escaped
1012         $new_str = html_attr($str);
1013         
return str_replace(array('&lt;', '&gt;'), array('<', '>'), $new_str);
1014     }
1015     #########################################################
1016     
class Request{
1017         
var $sql, $url, $attr, $html, $raw;
1018
1019         function __construct($
var, $filter = false){
1020             $
this->Request($var, $filter);
1021         }
1022
1023         function Request($
var, $filter = false){
1024             $
unsafe = (isset($_REQUEST[$var]) ? $_REQUEST[$var] : '');
1025             
if(get_magic_quotes_gpc()) $unsafe = stripslashes($unsafe);
1026
1027             
if($filter){
1028                 $
unsafe = call_user_func($filter, $unsafe);
1029             }
1030
1031             $
this->sql = makeSafe($unsafe, false);
1032             $
this->url = urlencode($unsafe);
1033             $
this->attr = html_attr($unsafe);
1034             $
this->html = html_attr($unsafe);
1035             $
this->raw = $unsafe;
1036         }
1037     }
1038     #########################################################
1039     
class Notification{
1040         
/*
1041             Usage:
1042             *
in the main document, initiate notifications support using this PHP code:
1043                 echo Notification::placeholder();
1044
1045             * whenever you want to show a notifcation, use
this PHP code:
1046                 echo Notification::show(array(
1047                     
'message' => 'Notification text to display',
1048                     
'class' => 'danger', // or other bootstrap state cues, 'default' if not provided
1049                     
'dismiss_seconds' => 5, // optional auto-dismiss after x seconds
1050                     
'dismiss_days' => 7, // optional dismiss for x days if closed by user -- must provide an id
1051                     
'id' => 'xyz' // optional string to identify the notification -- must use for 'dismiss_days' to work
1052                 ));
1053         */

1054         
protected static $placeholder_id; /* to force a single notifcation placeholder */
1055
1056         
protected function __construct(){} /* to prevent initialization */
1057
1058         
public static function placeholder(){
1059             
if(self::$placeholder_id) return ''; // output placeholder code only once
1060
1061             self::$placeholder_id =
'notifcation-placeholder-' . rand(10000000, 99999999);
1062
1063             ob_start();
1064             ?>
1065
1066             <div
class="notifcation-placeholder" id="<?php echo self::$placeholder_id; ?>"></div>
1067             <script>
1068                 $j(function(){
1069                     
if(window.show_notification != undefined) return;
1070
1071                     window.show_notification = function(options){
1072                         
/* wait till all dependencies ready */
1073                         
if(window.notifications_ready == undefined){
1074                             
var op = options;
1075                             setTimeout(function(){
/* */ show_notification(op); }, 20);
1076                             
return;
1077                         }
1078
1079                         
var dismiss_class = '';
1080                         
var dismiss_icon = '';
1081                         
var cookie_name = 'hide_notification_' + options.id;
1082                         
var notif_id = 'notifcation-' + Math.ceil(Math.random() * 1000000);
1083
1084                         
/* apply provided notficiation id if unique in page */
1085                         
if(options.id != undefined){
1086                             
if(!$j('#' + options.id).length) notif_id = options.id;
1087                         }
1088
1089                         
/* notifcation should be hidden? */
1090                         
if(Cookies.get(cookie_name) != undefined) return;
1091
1092                         
/* notification should be dismissable? */
1093                         
if(options.dismiss_seconds > 0 || options.dismiss_days > 0){
1094                             dismiss_class =
' alert-dismissible';
1095                             dismiss_icon =
'<button type="button" class="close" data-dismiss="alert">&times;</button>';
1096                         }
1097
1098                         
/* remove old dismissed notficiations */
1099                         $j(
'.alert-dismissible.invisible').remove();
1100
1101                         
/* append notification to notifications container */
1102                         $j(
1103                             
'<div class="alert alert-' + options['class'] + dismiss_class + '" id="' + notif_id + '">' +
1104                                 dismiss_icon +
1105                                 options.message +
1106                             
'</div>'
1107                         ).appendTo(
'#<?php echo self::$placeholder_id; ?>');
1108
1109                         
var this_notif = $j('#' + notif_id);
1110
1111                         
/* dismiss after x seconds if requested */
1112                         
if(options.dismiss_seconds > 0){
1113                             setTimeout(function(){
/* */ this_notif.addClass('invisible'); }, options.dismiss_seconds * 1000);
1114                         }
1115
1116                         
/* dismiss for x days if requested and user dismisses it */
1117                         
if(options.dismiss_days > 0){
1118                             
var ex_days = options.dismiss_days;
1119                             this_notif.
on('closed.bs.alert', function(){
1120                                 
/* set a cookie not to show this alert for ex_days */
1121                                 Cookies.
set(cookie_name, '1', { expires: ex_days });
1122                             });
1123                         }
1124                     }
1125
1126                     
/* cookies library already loaded? */
1127                     
if(undefined != window.Cookies){
1128                         window.notifications_ready =
true;
1129                         
return;
1130                     }
1131
1132                     
/* load cookies library */
1133                     $j.ajax({
1134                         url:
'<?php echo PREPEND_PATH; ?>resources/jscookie/js.cookie.js',
1135                         dataType:
'script',
1136                         cache:
true,
1137                         success: function(){
/* */ window.notifications_ready = true; }
1138                     });
1139                 })
1140             </script>
1141
1142             <?php
1143             $html = ob_get_contents();
1144             ob_end_clean();
1145
1146             
return $html;
1147         }
1148
1149         
protected static function default_options(&$options){
1150             
if(!isset($options['message'])) $options['message'] = 'Notification::show() called without a message!';
1151
1152             
if(!isset($options['class'])) $options['class'] = 'default';
1153
1154             
if(!isset($options['dismiss_seconds']) || isset($options['dismiss_days'])) $options['dismiss_seconds'] = 0;
1155
1156             
if(!isset($options['dismiss_days'])) $options['dismiss_days'] = 0;
1157             
if(!isset($options['id'])){
1158                 $options[
'id'] = 0;
1159                 $options[
'dismiss_days'] = 0;
1160             }
1161         }
1162
1163         
/**
1164          * @brief Notification::show($options) displays a notification
1165          *
1166          * @param $options assoc array
1167          *
1168          * @
return html code for displaying the notifcation
1169          */

1170         
public static function show($options = array()){
1171             self::default_options($options);
1172
1173             ob_start();
1174             ?>
1175             <script>
1176                 $j(function(){
1177                     show_notification(<?php echo json_encode($options); ?>);
1178                 })
1179             </script>
1180             <?php
1181             $html = ob_get_contents();
1182             ob_end_clean();
1183
1184             
return $html;
1185         }
1186     }
1187     #########################################################
1188     function sendmail($mail){
1189         
if(!isset($mail['to'])) return 'No recipient defined';
1190         
if(!isEmail($mail['to'])) return 'Invalid recipient email';
1191
1192         $mail[
'subject'] = isset($mail['subject']) ? $mail['subject'] : '';
1193         $mail[
'message'] = isset($mail['message']) ? $mail['message'] : '';
1194         $mail[
'name'] = isset($mail['name']) ? $mail['name'] : '';
1195         $mail[
'debug'] = isset($mail['debug']) ? min(4, max(0, intval($mail['debug']))) : 0;
1196
1197         $cfg = config(
'adminConfig');
1198         $smtp = ($cfg[
'mail_function'] == 'smtp');
1199
1200         
if(!class_exists('PHPMailer')){
1201             $curr_dir = dirname(__FILE__);
1202             include(
"{$curr_dir}/../resources/PHPMailer/class.phpmailer.php");
1203             
if($smtp) include("{$curr_dir}/../resources/PHPMailer/class.smtp.php");
1204         }
1205
1206         $pm =
new PHPMailer;
1207         $pm->CharSet = datalist_db_encoding;
1208
1209         
if($smtp){
1210             $pm->isSMTP();
1211             $pm->SMTPDebug = $mail[
'debug'];
1212             $pm->Debugoutput =
'html';
1213             $pm->Host = $cfg[
'smtp_server'];
1214             $pm->Port = $cfg[
'smtp_port'];
1215             $pm->SMTPAuth =
true;
1216             $pm->SMTPSecure = $cfg[
'smtp_encryption'];
1217             $pm->Username = $cfg[
'smtp_user'];
1218             $pm->Password = $cfg[
'smtp_pass'];
1219         }
1220
1221         $pm->setFrom($cfg[
'senderEmail'], $cfg['senderName']);
1222         $pm->addAddress($mail[
'to'], $mail['name']);
1223         $pm->Subject = $mail[
'subject'];
1224
1225         
/* if message already contains html tags, don't apply nl2br */
1226         
if($mail['message'] == strip_tags($mail['message']))
1227             $mail[
'message'] = nl2br($mail['message']);
1228
1229         $pm->msgHTML($mail[
'message'], realpath("{$curr_dir}/.."));
1230
1231         
/* if sendmail_handler(&$pm) is defined (in hooks/__global.php) */
1232         
if(function_exists('sendmail_handler')) sendmail_handler($pm);
1233
1234         
if(!$pm->send()) return $pm->ErrorInfo;
1235
1236         
return true;
1237     }
1238     #########################################################
1239     function safe_html($str){
1240         
/* if $str has no HTML tags, apply nl2br */
1241         
if($str == strip_tags($str)) return nl2br($str);
1242
1243         $hc =
new CI_Input();
1244         $hc->charset = datalist_db_encoding;
1245
1246         
return $hc->xss_clean($str);
1247     }
1248     #########################################################
1249     function getLoggedGroupID(){
1250         
if($_SESSION['memberGroupID']!=''){
1251             
return $_SESSION['memberGroupID'];
1252         }
else{
1253             
if(!setAnonymousAccess()) return false;
1254             
return getLoggedGroupID();
1255         }
1256     }
1257     #########################################################
1258     function getLoggedMemberID(){
1259         
if($_SESSION['memberID']!=''){
1260             
return strtolower($_SESSION['memberID']);
1261         }
else{
1262             
if(!setAnonymousAccess()) return false;
1263             
return getLoggedMemberID();
1264         }
1265     }
1266     #########################################################
1267     function setAnonymousAccess(){
1268         $adminConfig = config(
'adminConfig');
1269         $anon_group_safe = addslashes($adminConfig[
'anonymousGroup']);
1270         $anon_user_safe = strtolower(addslashes($adminConfig[
'anonymousMember']));
1271
1272         $eo = array(
'silentErrors' => true);
1273
1274         $res = sql(
"select groupID from membership_groups where name='{$anon_group_safe}'", $eo);
1275         
if(!$res){ return false; }
1276         $row = db_fetch_array($res); $anonGroupID = $row[
0];
1277
1278         $_SESSION[
'memberGroupID'] = ($anonGroupID ? $anonGroupID : 0);
1279
1280         $res = sql(
"select lcase(memberID) from membership_users where lcase(memberID)='{$anon_user_safe}' and groupID='{$anonGroupID}'", $eo);
1281         
if(!$res){ return false; }
1282         $row = db_fetch_array($res); $anonMemberID = $row[
0];
1283
1284         $_SESSION[
'memberID'] = ($anonMemberID ? $anonMemberID : 0);
1285
1286         
return true;
1287     }
1288     #########################################################
1289     function getMemberInfo($memberID =
''){
1290         
static $member_info = array();
1291
1292         
if(!$memberID){
1293             $memberID = getLoggedMemberID();
1294         }
1295
1296         
// return cached results, if present
1297         
if(isset($member_info[$memberID])) return $member_info[$memberID];
1298
1299         $adminConfig = config(
'adminConfig');
1300         $mi = array();
1301
1302         
if($memberID){
1303             $res = sql(
"select * from membership_users where memberID='" . makeSafe($memberID) . "'", $eo);
1304             
if($row = db_fetch_assoc($res)){
1305                 $mi = array(
1306                     
'username' => $memberID,
1307                     
'groupID' => $row['groupID'],
1308                     
'group' => sqlValue("select name from membership_groups where groupID='{$row['groupID']}'"),
1309                     
'admin' => ($adminConfig['adminUsername'] == $memberID ? true : false),
1310                     
'email' => $row['email'],
1311                     
'custom' => array(
1312                         $row[
'custom1'],
1313                         $row[
'custom2'],
1314                         $row[
'custom3'],
1315                         $row[
'custom4']
1316                     ),
1317                     
'banned' => ($row['isBanned'] ? true : false),
1318                     
'approved' => ($row['isApproved'] ? true : false),
1319                     
'signupDate' => @date('n/j/Y', @strtotime($row['signupDate'])),
1320                     
'comments' => $row['comments'],
1321                     
'IP' => $_SERVER['REMOTE_ADDR']
1322                 );
1323
1324                 
// cache results
1325                 $member_info[$memberID] = $mi;
1326             }
1327         }
1328
1329         
return $mi;
1330     }
1331     #########################################################
1332     function get_group_id($user =
''){
1333         $mi = getMemberInfo($user);
1334         
return $mi['groupID'];
1335     }
1336     #########################################################
1337     
/**
1338      * @brief Prepares data
for a SET or WHERE clause, to be used in an INSERT/UPDATE query
1339      *
1340      * @param [
in] $set_array Assoc array of field names => values
1341      * @param [
in] $glue optional glue. Set to ' AND ' or ' OR ' if preparing a WHERE clause
1342      * @
return SET string
1343      */

1344     function prepare_sql_set($set_array, $glue =
', '){
1345         $fnvs = array();
1346         
foreach($set_array as $fn => $fv){
1347             
if($fv === null){ $fnvs[] = "{$fn}=NULL"; continue; }
1348
1349             $sfv = makeSafe($fv);
1350             $fnvs[] =
"{$fn}='{$sfv}'";
1351         }
1352         
return implode($glue, $fnvs);
1353     }
1354     #########################################################
1355     
/**
1356      * @brief Inserts a record to the database
1357      *
1358      * @param [
in] $tn table name where the record would be inserted
1359      * @param [
in] $set_array Assoc array of field names => values to be inserted
1360      * @
return boolean indicating success/failure
1361      */

1362     function insert($tn, $set_array){
1363         $
set = prepare_sql_set($set_array);
1364         
if(!count($set)) return false;
1365
1366         
return sql("INSERT INTO `{$tn}` SET {$set}", $eo);
1367     }
1368     #########################################################
1369     
/**
1370      * @brief Updates a record
in the database
1371      *
1372      * @param [
in] $tn table name where the record would be inserted
1373      * @param [
in] $set_array Assoc array of field names => values to be inserted
1374      * @param [
in] $where_array Assoc array of field names => values used to build the WHERE clause
1375      * @
return boolean indicating success/failure
1376      */

1377     function update($tn, $set_array, $where_array){
1378         $
set = prepare_sql_set($set_array);
1379         
if(!count($set)) return false;
1380
1381         $
where = prepare_sql_set($where_array, ' AND ');
1382         
if(!$where) $where = '1=1';
1383
1384         
return sql("UPDATE `{$tn}` SET {$set} WHERE {$where}", $eo);
1385     }
1386     #########################################################
1387     
/**
1388      * @brief Set/update the owner of given record
1389      *
1390      * @param [
in] $tn name of table
1391      * @param [
in] $pk primary key value
1392      * @param [
in] $user username to set as owner
1393      * @
return boolean indicating success/failure
1394      */

1395     function set_record_owner($tn, $pk, $user){
1396         $fields = array(
1397             
'memberID' => strtolower($user),
1398             
'dateUpdated' => time(),
1399             
'groupID' => get_group_id($user)
1400         );
1401
1402         $where_array = array(
'tableName' => $tn, 'pkValue' => $pk);
1403         $
where = prepare_sql_set($where_array, ' AND ');
1404         
if(!$where) return false;
1405
1406         
/* do we have an ownership record? */
1407         $existing_owner = sqlValue(
"select LCASE(memberID) from membership_userrecords where {$where}");
1408         
if($existing_owner == $user) return true; // owner already set to $user
1409
1410         
/* update owner */
1411         
if($existing_owner){
1412             $res = update(
'membership_userrecords', $fields, $where_array);
1413             
return ($res ? true : false);
1414         }
1415
1416         
/* add new ownership record */
1417         $fields = array_merge($fields, $where_array, array(
'dateAdded' => time()));
1418         $res = insert(
'membership_userrecords', $fields);
1419         
return ($res ? true : false);
1420     }
1421     #########################################################
1422     
/**
1423      * @brief
get date/time format string for use in different cases.
1424      *
1425      * @param [
in] $destination string, one of these: 'php' (see date function), 'mysql', 'moment'
1426      * @param [
in] $datetime string, one of these: 'd' = date, 't' = time, 'dt' = both
1427      * @
return string
1428      */

1429     function app_datetime_format($destination =
'php', $datetime = 'd'){
1430         
switch(strtolower($destination)){
1431             
case 'mysql':
1432                 $date =
'%m/%d/%Y';
1433                 $time =
'%h:%i:%s %p';
1434                 
break;
1435             
case 'moment':
1436                 $date =
'MM/DD/YYYY';
1437                 $time =
'hh:mm:ss A';
1438                 
break;
1439             
default: // php
1440                 $date =
'm/d/Y';
1441                 $time =
'h:i:s A';
1442         }
1443
1444         $datetime = strtolower($datetime);
1445         
if($datetime == 'dt' || $datetime == 'td') return "{$date} {$time}";
1446         
if($datetime == 't') return $time;
1447         
return $date;
1448     }
1449     #########################################################
1450     
/**
1451      * @param [
in] $app_datetime string, a datetime formatted in app-specific format
1452      * @
return string, mysql-formatted datetime, 'yyyy-mm-dd H:i:s', or empty string on error
1453      */

1454     function mysql_datetime($app_datetime, $date_format =
null, $time_format = null){
1455         $app_datetime = trim($app_datetime);
1456
1457         
if($date_format === null) $date_format = app_datetime_format('php', 'd');
1458         $date_separator = $date_format[
1];
1459         
if($time_format === null) $time_format = app_datetime_format('php', 't');
1460         $time24 = (strpos($time_format,
'H') !== false); // true if $time_format is 24hr rather than 12
1461
1462         $date_regex = str_replace(
1463             array(
'Y', 'm', 'd', '/', '.'),
1464             array(
'([0-9]{4})', '(1[012]|0?[1-9])', '([12][0-9]|3[01]|0?[1-9])', '\/', '\.'),
1465             $date_format
1466         );
1467
1468         $time_regex = str_replace(
1469             array(
'H', 'h', ':i', ':s'),
1470             array(
1471                 
'(1[0-9]|2[0-3]|0?[0-9])',
1472                 
'(1[012]|0?[0-9])',
1473                 
'(:([1-5][0-9]|0?[0-9]))',
1474                 
'(:([1-5][0-9]|0?[0-9]))?'
1475             ),
1476             $time_format
1477         );
1478         
if(stripos($time_regex, ' a'))
1479             $time_regex = str_replace(array(
' a', ' A'), '\s*(am|pm|a|p)?', $time_regex);
1480         
else
1481             $time_regex = str_replace(array(
'a', 'A'), '\s*(am|pm|a|p)?', $time_regex);
1482
1483         
// extract date and time
1484         $time =
'';
1485         $mat = array();
1486         $regex =
"/^({$date_regex})(\s+{$time_regex})?$/i";
1487         $valid_dt = preg_match($regex, $app_datetime, $mat);
1488         
if(!$valid_dt || count($mat) < 5) return ''; // invlaid datetime
1489         
// if we have a time, get it and change 'a' or 'p' at the end to 'am'/'pm'
1490         
if(count($mat) >= 8) $time = preg_replace('/(a|p)$/i', '$1m', trim($mat[5]));
1491
1492         
// extract date elements from regex match, given 1st 2 items are full string and full date
1493         $date_order = str_replace($date_separator,
'', $date_format);
1494         $day = $mat[stripos($date_order,
'd') + 2];
1495         $month = $mat[stripos($date_order,
'm') + 2];
1496         $year = $mat[stripos($date_order,
'y') + 2];
1497
1498         
// convert time to 24hr format if necessary
1499         
if($time && !$time24) $time = date('H:i:s', strtotime("2000-01-01 {$time}"));
1500
1501         $mysql_datetime = trim(
"{$year}-{$month}-{$day} {$time}");
1502
1503         
// strtotime handles dates between 1902 and 2037 only
1504         
// so we need another test date for dates outside this range ...
1505         $test = $mysql_datetime;
1506         
if($year < 1902 || $year > 2037) $test = str_replace($year, '2000', $mysql_datetime);
1507
1508         
return (strtotime($test) ? $mysql_datetime : '');
1509     }
1510     #########################################################
1511     
/**
1512      * @param [
in] $mysql_datetime string, Mysql-formatted datetime
1513      * @param [
in] $datetime string, one of these: 'd' = date, 't' = time, 'dt' = both
1514      * @
return string, app-formatted datetime, or empty string on error
1515      *
1516      * @details works
for formatting date, time and datetime, based on 2nd param
1517      */

1518     function app_datetime($mysql_datetime, $datetime =
'd'){
1519         $pyear = $myear = substr($mysql_datetime,
0, 4);
1520
1521         
// strtotime handles dates between 1902 and 2037 only
1522         
// so we need a temp date for dates outside this range ...
1523         
if($myear < 1902 || $myear > 2037) $pyear = 2000;
1524         $mysql_datetime = str_replace($myear, $pyear, $mysql_datetime);
1525
1526         $ts = strtotime($mysql_datetime);
1527         
if(!$ts) return '';
1528
1529         $pdate = date(app_datetime_format(
'php', $datetime), $ts);
1530         
return str_replace($pyear, $myear, $pdate);
1531     }
1532     #########################################################
1533     
/**
1534      * @brief converts
string from app-configured encoding to utf8
1535      *
1536      * @param [
in] $str string to convert to utf8
1537      * @
return utf8-encoded string
1538      *
1539      * @details
if the constant 'datalist_db_encoding' is not defined, original string is returned
1540      */

1541     function to_utf8($str) {
1542         
if(!defined('datalist_db_encoding')) return $str;
1543         
if(datalist_db_encoding == 'UTF-8') return $str;
1544         
return iconv(datalist_db_encoding, 'UTF-8', $str);
1545     }
1546     #########################################################
1547     
/**
1548      * @brief converts
string from utf8 to app-configured encoding
1549      *
1550      * @param [
in] $str string to convert from utf8
1551      * @
return utf8-decoded string
1552      *
1553      * @details
if the constant 'datalist_db_encoding' is not defined, original string is returned
1554      */

1555     function from_utf8($str) {
1556         
if(!defined('datalist_db_encoding')) return $str;
1557         
if(datalist_db_encoding == 'UTF-8') return $str;
1558         
return iconv('UTF-8', datalist_db_encoding, $str);
1559     }



Hệ thống xếp lịch học tín chỉ cho sinh viên CNTT trên PHP & MySQL 112.147 lượt xem

Gõ tìm kiếm nhanh...